﻿/*
 *  date: 2018-07-05
 *  author: John-chen
 *  cn: 基础UI框架
 *  en: todo:
 */

using UnityEngine;
using System.Collections;

namespace JyFramework
{
    /// <summary>
    /// 基础UI框架
    /// 将View 和 Controller
    /// </summary>
    public class BaseWindow : IUILife, IEvent
    {
        /// <summary>
        /// 窗口名字
        /// </summary>
        public string Name { get { return _name;} }

        /// <summary>
        /// 窗口信息
        /// </summary>
        public WindowInfo WndInfo { get { return _wndInfo;} }

        public BaseWindow()
        {
            SetName();
            _eventCtrl = new EventController(_name + "EventCtrl");
            MessageCtrl.Ins.AddEventCtrl(_eventCtrl);

            _resLoader = JyApp.Ins.GetModule<ResourceModule>(ModuleName.Res).Loader;
        }

        /// <summary>
        /// 加载UI资源
        /// </summary>
        /// <param name="path"></param>
        /// <param name="action"></param>
        public void SetWndInfo(WindowInfo wndInfo, WndAction action = null)
        {
            _wndInfo = wndInfo;
            _prefabPath = wndInfo.Path;
            LoadWnd(action);
        }

        /// <summary>
        /// 窗口节点
        /// </summary>
        public GameObject gameObject { get { return _obj; } } 

        /// <summary>
        /// 初始化窗口时调用
        /// </summary>
        public virtual void OnInit()
        {
            
        }

        /// <summary>
        /// 窗口显示前调用
        /// </summary>
        public virtual void OnBeforeShow()
        {
            
        }

        /// <summary>
        /// 窗口显示后调用
        /// </summary>
        public virtual void OnShow()
        {
            
        }

        /// <summary>
        /// 窗口显示时每帧调用
        /// </summary>
        /// <param name="deltaTime"></param>
        public virtual void OnUpdate(float deltaTime)
        {

        }

        /// <summary>
        /// 窗口被影藏时调用
        /// </summary>
        public virtual void OnHide()
        {
            
        }

        /// <summary>
        /// 窗口被销毁时调用
        /// </summary>
        public virtual void OnRemove()
        {
            MessageCtrl.Ins.RemoveCtrl(_eventCtrl);
        }

        /// <summary>
        /// 注册事件
        /// </summary>
        /// <param name="name"></param>
        /// <param name="eventActioin"></param>
        public void RegistEvent(string name, MessageHandler eventActioin)
        {
            _eventCtrl.RegistEvent(name, eventActioin);
        }

        /// <summary>
        /// 通知事件
        /// </summary>
        /// <param name="name"></param>
        /// <param name="args"></param>
        public void NotifyEvent(string name, params object[] args)
        {
            _eventCtrl.NotifyEvent(name, args);
        }

        /// <summary>
        /// 移除事件
        /// </summary>
        /// <param name="name"></param>
        /// <param name="eventAction"></param>
        public void RemoveEvent(string name, MessageHandler eventAction)
        {
            _eventCtrl.RemoveEvent(name, eventAction);
        }

        /// <summary>
        /// 更新窗口缓存
        /// </summary>
        public void RefreshWndCache()
        {
            _wndInfo.UpdateTime();
        }

        /// <summary>
        /// 检测本身是否达到缓存时间
        /// </summary>
        /// <returns></returns>
        public bool CheckCacheTime()
        {
            float curTime = Time.realtimeSinceStartup;
            float winRefreshTime = _wndInfo.RefreshTime;
            WindowCacheTime cacheTime = _wndInfo.CacheTime;

            bool isNeedDestroy = false;
            int cTime = 0;

            switch (cacheTime)
            {
                case WindowCacheTime.Cache0:
                    cTime = -1;
                    break;
                case WindowCacheTime.Cache1:
                    cTime = (int)WindowCacheTime.Cache1 * 60;
                    break;
                case WindowCacheTime.Cache5:
                    cTime = (int)WindowCacheTime.Cache5 * 60;
                    break;
                case WindowCacheTime.Cache10:
                    cTime = (int)WindowCacheTime.Cache10 * 60;
                    break;
                case WindowCacheTime.Cache30:
                    cTime = (int)WindowCacheTime.Cache30 * 60;
                    break;
                case WindowCacheTime.Cache60:
                    cTime = (int)WindowCacheTime.Cache60 * 60;
                    break;
                case WindowCacheTime.CacheMax:
                    cTime = -2;
                    break;
            }

            if (cTime > 0)
            {
                isNeedDestroy = (curTime - winRefreshTime) > cTime;
            }
            else
            {
                if (cTime == -1) isNeedDestroy = true;
                if (cTime == -2) isNeedDestroy = false;
            }

            return isNeedDestroy;
        }

        /// <summary>
        /// 销毁自身
        /// </summary>
        public void Destroy()
        {
            OnRemove();
            Object.DestroyImmediate(_obj);
        }

        /// <summary>
        /// 加载窗口
        /// </summary>
        private void LoadWnd(WndAction action = null)
        {
            if (string.IsNullOrEmpty(_prefabPath))
            {
                Debug.LogError(string.Format("The {0} path is empty!", this.GetType()));
                return;
            }

            string uiPath = PathHelper.UIPath + _prefabPath + "." + PathHelper.AssetBundleVariant;
            var wndObj = Object.Instantiate(LoadUIRes<GameObject>(uiPath));
            _obj = wndObj;
            _wndInfo.UpdateLoadedTime();

            action?.Execute();
        }

        /// <summary>
        /// 开启一个协程
        /// </summary>
        /// <param name="routine"></param>
        /// <returns></returns>
        protected Coroutine StartCoroutine(IEnumerator routine)
        {
            return MonoHelper.Ins.StartCoroutine(routine);
        }


        /// <summary>
        /// 异步加载一个对象
        /// </summary>
        /// <param name="yieldArg"></param>
        protected void AsyncLoadUIRes(YieldArgs yieldArg, AsyncLoadedHandle action)
        {
            StartCoroutine(_resLoader.AsyncLoadRes(yieldArg, action));
        }

        /// <summary>
        /// 同步加载ui对象
        /// </summary>
        /// <param name="path"></param>
        /// <returns></returns>
        protected T LoadUIRes<T>(string path) where T : Object
        {
            return _resLoader.LoadRes<T>(path);
        }

        /// <summary>
        /// 设置当前窗口的名字
        /// </summary>
        private void SetName()
        {
            var nspace = "GameCore.";
            var myType = GetType().ToString();
            _name = myType.Substring(nspace.Length);
        }

        protected string _name;
        protected GameObject _obj;
        protected WindowInfo _wndInfo;
        protected ResLoader _resLoader;
        protected string _prefabPath = "";
        protected EventController _eventCtrl;
    }


}